Building a WCF Service

Now that you have a better understanding about the building blocks of a WCF application, it’s time to create your first sample application and see how the ABCs are accounted for in code and configuration. This first example avoids using the Visual Studio 2010 WCF project templates, so you can focus on the specific steps involved in making a WCF service.

Begin by creating a new C# Class Library project named MagicEightBallServiceLib. Next, rename your initial file from Class1.cs to MagicEightBallService.cs, and then add a reference to the System.ServiceModel.dll assembly. In the initial code file, specify that you are using the System.ServiceModel namespace. At this point, your C# file should look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// The key WCF namespace.
using System.ServiceModel;

namespace MagicEightBallServiceLib
{
    public class MagicEightBallService
    {
    }
}

Your class type implements a single WCF service contract represented by a strongly typed CLR interface named IEightBall. As you most likely know, the Magic 8-Ball is a toy that allows you to view one of a handful of fixed answers to a question you might ask. Your interface here will define a single method that allows the caller to pose a question to the Magic 8-Ball to obtain a random answer.

WCF service interfaces are adorned with the [ServiceContract] attribute, while each interface member is decorated with the [OperationContract] attribute (you’ll learn more details regarding these two attributes in just a moment). Here is the definition of the IEightBall interface:

[ServiceContract]
public interface IEightBall
{
    // Ask a question, receive an answer!
    [OperationContract]
    string ObtainAnswerToQuestion(string userQuestion);
}

Note It is permissible to define a service contract interface that contains methods not adorned with the [OperationContract] attribute; however, such members will not be exposed through the WCF runtime.

As you know from your study of the interface type (see Chapter 9), interfaces are quite useless until they are implemented by a class or structure that fleshes out their functionality. Like a real Magic 8-Ball, the implementation of your service type (MagicEightBallService) will randomly return a canned answer from an array of strings. Also, your default constructor will display an information message that will be (eventually) displayed within the host’s console window (for diagnostic purposes):

public class MagicEightBallService : IEightBall
{
    // Just for display purposes on the host.
    public MagicEightBallService()
    {
        Console.WriteLine("The 8-Ball awaits your question...");
    }

    public string ObtainAnswerToQuestion(string userQuestion)
    {
        string[] answers = { "Future Uncertain", "Yes", "No",
            "Hazy", "Ask again later", "Definitely" };

        // Return a random response.
        Random r = new Random();
        return answers[r.Next(answers.Length)];
    }
}

At this point, your WCF service library is complete. However, before you construct a host for this service, you need to examine some additional details of the [ServiceContract] and [OperationContract] attributes.

The [ServiceContract] Attribute

For a CLR interface to participate in the services provided by WCF, it must be adorned with the [ServiceContract] attribute. Like many other .NET attributes, the ServiceContractAttribute type supports many properties that further qualify its intended purpose. You can set two properties, Name and Namespace, to control the name of the service type and the name of the XML namespace that defines the service type. If you use a web service–specific binding, you use these values to define the <portType> elements of the related WSDL document.

Here, you do not bother to assign a Name value because the default name of the service type is directly based on the C# class name. However, the default name for the underlying XML namespace is simply http://tempuri.org (you should change this for all of your WCF services).

When you build a WCF service that will send and receive custom data types (which you are not currently doing), it is important that you establish a meaningful value to the underlying XML namespace because this ensures that your custom types are unique. As you might know from your experience building XML web services, XML namespaces provide a way to wrap your custom types in a unique container to ensure that your types do not clash with types in another organization.

For this reason, you can update your interface definition with a more fitting definition, which, much like the process of defining an XML namespace in a .NET Web Service project, is typically the URI of the service’s point of origin, as in the following example:

[ServiceContract(Namespace = "http://MyCompany.com")]
public interface IEightBall
{
    ...
}

Beyond Namespace and Name, the [ServiceContract] attribute can be configured with the additional properties shown in Table 25-6. Be aware that some of these settings will be ignored, depending on your binding selection.

Table 25-6. Various Named Properties of the [ServiceContract] Attribute

Property Meaning in Life
CallbackContract Establishes whether this service contract requires callback functionality for two-way message exchange (e.g., duplex bindings).
ConfigurationName You use this name to locate the service element in an application configuration file. The default is the name of the service implementation class.
ProtectionLevel Allows you to specify the degree to which the contract binding requires encryption, digital signatures, or both for endpoints that expose the contract.
SessionMode You use this to establish whether sessions are allowed, not allowed, or required by this service contract.

The [OperationContract] Attribute

Methods that you wish to use within the WCF framework must be attributed with the [OperationContract] attribute, which can also be configured with various named properties. You can use the properties shown in Table 25-7 to declare that a given method is intended to be one-way in nature, supports asynchronous invocation, requires encrypted message data, and so forth (again, many of these values might be ignored based on your binding selection).

Table 25-7. Various Named Properties of the [OperationContract] Attribute

Property Meaning in Life
AsyncPattern Indicates whether the operation is implemented asynchronously using a Begin/End method pair on the service. This allows the service to offload processing to another server-side thread; this has nothing to do with the client calling the method asynchronously!
IsInitiating Specifies whether this operation can be the initial operation in a session.
IsOneWay Indicates whether the operation consists of only a single input message (and no associated output).
IsTerminating Specifies whether the WCF runtime should attempt to terminate the current session after the operation completes.

For the initial example, you don’t need to configure the ObtainAnswerToQuestion() method with additional traits; this means you can use the [OperationContract] attribute as currently defined.

Service Types As Operational Contracts

Finally, recall that the use of interfaces is not required when building WCF service types. In fact, it is possible to apply the [ServiceContract] and [OperationContract] attributes directly to the service type itself:

// This is only for illustrative purposes
// and not used for the current example.
[ServiceContract(Namespace = "http://MyCompany.com")]
public class ServiceTypeAsContract
{    
    [OperationContract]
    void SomeMethod() { }

    [OperationContract]
    void AnotherMethod() { }
}

You can take this approach; however, you receive many benefits if you explicitly define an interface type to represent the service contract. The most obvious benefit is that you can apply a given interface to multiple service types (authored in a variety of languages and architectures) to achieve a high degree of polymorphism. Another benefit: You can use a service contract interface as the basis of new contracts (using interface inheritance), without having to carry any implementation baggage.

In any case, your first WCF service library is now complete. Compile your project to ensure you do not have any typos.

Source Code You can find the MagicEightBallServiceLib project under the MagicEightBallServiceHTTP directory of Chapter 25.